/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package ip

import (
	"io/ioutil"
	"gitee.com/tugoer/orivil/mux"
	"net/http"
	"bytes"
	"encoding/json"
	"fmt"
	"sync"
	"net"
	"strings"
)

// 服务器本机地址
var ipAddress = getIPAddress()

// DNS 服务器 IP 地址容器
var container = &struct {
	ips map[string]string
	locker sync.RWMutex
}{
	ips: make(map[string]string, 20),
}

func getWebSiteIP(domain string) (ip string, err error) {
	container.locker.RLock()
	ip = container.ips[domain]
	container.locker.RUnlock()
	if ip != "" {
		return ip, nil
	} else {
		ls, e := net.LookupHost(domain)
		if e != nil {
			err = e
			return
		} else {
			for _, ip = range ls {
				container.locker.Lock()
				container.ips[domain] = ip
				container.locker.Unlock()
				return ip, nil
			}
		}
	}
	return "", fmt.Errorf("domain %s get ip field", domain)
}

type CitySN struct {
	CIP string `json:"cip"`
	CID string `json:"cid"`
	CName string `json:"cname"`
}

func getIPAddress() string {
	resp, err := http.Get("http://pv.sohu.com/cityjson?ie=utf-8")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	jsonStart := bytes.Index(content, []byte("{"))
	jsonEnd := bytes.Index(content, []byte("}"))
	if 0<=jsonStart && jsonStart < jsonEnd {
		content = content[jsonStart:jsonEnd+1]
		csn := &CitySN{}
		err = json.Unmarshal(content, csn)
		if err != nil {
			panic(err)
		}
		return csn.CIP
	} else {
		panic(fmt.Errorf("got content: %s", content))
	}
}

var Actions = []*mux.Action{
	{
		Method: "GET", Route: "server-ip", Name: "Get Server IP Address",
		Handler: func(ctx *mux.Context) {
			ctx.SendJson(map[string]string{
				"ip": ipAddress,
			})
		},
		ApiDoc:&mux.ApiDoc{
			Tags: []string{Tag},
			Summary: "获得当前服务器 IP 地址",
			Responses:mux.Responses{
				"200": {
					Description: "success",
					Example: map[string]string{
						"ip": ipAddress,
					},
				},
			},
		},
	},
	{
		Method: "GET", Route: "domain-ip", Name: "Get Domain IP Address",
		Params: mux.Parameters{
			{
				In:mux.Query,
				Schema: &getWebServerIP{},
			},
		},
		Handler: func(ctx *mux.Context) {
			p := &getWebServerIP{}
			ctx.WarnParse(p)
			p.Domain = strings.TrimPrefix(p.Domain, "http://")
			p.Domain = strings.TrimPrefix(p.Domain, "https://")
			ip, err := getWebSiteIP(p.Domain)
			if err != nil {
				ctx.ErrWarning(err)
			} else {
				ctx.SendJson(map[string]string{
					"ip": ip,
				})
			}
		},
		ApiDoc:&mux.ApiDoc{
			Tags: []string{Tag},
			Summary: "获得域名所指向的 IP 地址",
			Description: "该地址由DNS服务器返回",
			Responses:mux.Responses{
				"200": {
					Description: "success",
					Example: map[string]string{
						"ip": ipAddress,
					},
				},
			},
		},
	},
}

type getWebServerIP struct {
	Domain string `param:"domain"`
}